﻿// Колесов 
using System;
using System.Collections;
using System.Data.OleDb;
using System.IO;
using Transfer.DataLayer;

namespace Transfer
{   
    /// <summary> Обеспечивает загрузку таблиц из DBF-файла.
    /// Данные из одной DBF-таблицы загружаются в две DataTable - шапка документа и спецификация.
    /// Не используется TableAdapter т.к. имя файла неизвестно на момент написания программы 
    /// и определяется в Run-Time.
    /// Способ применения:
    /// - создать объект класса
    /// - настроить параметры (имя входного файла, )
    /// - вызывать метод чтения записи до достижения конца файла.
    /// Метод чтения должен выполнить валидацию записи. Валидатор при обнаружении ошибки делает запись в лог
    /// и осуществляется переход к следующей записи.
    /// </summary>
    public class CsvReader
    {
        /// <summary> Имя файла-источника
        /// </summary>
        public string SourceFileName
        {
            get { return _sourceFileName; }
            set { _sourceFileName = value; }
        }
        private string _sourceFileName = string.Empty;

        /// <summary> Таблицы загруженных входных данных
        /// </summary>
        private InputDocDS inputDoc
        {
            get { return _inputDoc; }
            set { _inputDoc = value; }
        }
        private InputDocDS _inputDoc = new InputDocDS();

        /// <summary> Общее количество документов, загруженных из входного файла
        /// </summary>
        public int Count
        {
            get { return _count; }
        }
        private int _count = 0;

        public ValidateDoc Validator;

        /// <summary> Конструктор класса
        /// </summary>
        public CsvReader()
        {
            // Для валидации подключим внутренний метод. Он может быть переназначен.
            Validator = InternalValidator;      
        }

        /// <summary> Загрузка данных из указанного файла во внутренние таблицы и их нормализация.
        /// </summary>
        public void LoadData()
        {
            string srcName;     // Имя CSV-файла без пути
            
//            string ConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\TEMP\\;Extended Properties=\"text;HDR=YES;FMT=Delimited;CharacterSet=OEM\"";
            string ConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\TEMP\\;Extended Properties=\"text;HDR=NO;FMT=Delimited;CharacterSet=OEM\"";

            #region ["Изменим строку подключения с учетом установленного имени файла-источника"]
            OleDbConnectionStringBuilder csb = new OleDbConnectionStringBuilder();
            try
            {
                csb.ConnectionString = ConnString;
                csb.DataSource = Path.GetDirectoryName(SourceFileName);
                //srcName = Path.GetFileNameWithoutExtension(SourceFileName);
                srcName = Path.GetFileName(SourceFileName);
            }
            catch
            {
                throw new Exception("Неверно указан каталог с файлом-источником.\r\n" + SourceFileName);
            }
            #endregion

            // !!! Расширение файла должно быть CSV или TXT. !!!
//                "SELECT DISTINCT tr2_dt as date_doc, nmrep_doct as type_doc, nmrep_docn as num_doc, nak_gpl_cd as gpl_cd, nak_gpl_nm as gpl_nm, r_jrn_code as jrn_cd " +
            string docHdrCmd = String.Format(
                "SELECT DISTINCT F1 as date_doc, F2 as type_doc, F3 as num_doc, F4 as gpl_cd, F9 as jrn_cd " +
                " FROM {0} ",  srcName);
            OleDbDataAdapter docHdrDA = new OleDbDataAdapter(docHdrCmd, csb.ConnectionString);

//                "SELECT nmrep_docn as num_doc, rsnomnmalt as nom_nm, rsnomart as nom_cd, tr2_qt as qt, nmrep_ei as ei, tr2_sumopl as nom_sum " +
            string docDetailCmd = String.Format(
                "SELECT F3 as num_doc, F5 as nom_cd, F6 as qt, F7 as ei, F8 as nom_sum " +
                " FROM `{0}` ", srcName);
            OleDbDataAdapter docDetailDA = new OleDbDataAdapter(docDetailCmd, csb.ConnectionString);

            try
            {
                this.inputDoc.DocHeader.Clear();
                this.inputDoc.DocDetail.Clear();
                docHdrDA.Fill(this.inputDoc, "DocHeader");
                docDetailDA.Fill(this.inputDoc, "DocDetail");
            }
            catch (Exception ex)
            {
                throw new Exception("Ошибка загрузки файла-источника.\r\n" + ex.Message, ex.InnerException);
            }
            // Количество прочитаных документов из входного файла
            this._count = this.inputDoc.DocHeader.Rows.Count;
        }

        /// <summary> Прочитать очередную запись. 
        /// Запись валидируется и, если содержит ошибки, она пропускается и переходим к следующей.
        /// Одновременно с валидацией дополняем запись данными из ИС-ПРО.
        /// </summary>
        public IEnumerator GetEnumerator()
        {
            foreach (InputDocDS.DocHeaderRow row in inputDoc.DocHeader.Rows)
            {
                if ( Validator(row))
                    yield return row;
            }
        }

        /// <summary> Заглушка для метода проверки текущего документа. 
        /// </summary>
        /// <param name="dataRow">Заголовочная запись документа</param>
        /// <returns>Если проверка успешно прошла, возвращает true, иначе - false</returns>
        private bool InternalValidator(System.Data.DataRow dataRow)
        {
            return true;
        }

        ///// <summary> Перевод даты из DateTime к виду, воспринимаемому OleDB командой
        ///// </summary>
        ///// <param name="dt"> Переводимая дата </param>
        ///// <returns> Строковое представление даты </returns>
        //public static string OleDBdate(DateTime dt)
        //{
        //    string year = dt.Year.ToString();
        //    string month = dt.Month.ToString();
        //    string day = dt.Day.ToString();
        //    string DLM = "-";
        //    return "{" + month + DLM + day + DLM + year + "}";
        //    // {2006-5-23}
        //}

    }
}
